#ifndef LEXICAL_H
#define LEXICAL_H
#include<iostream>
using std::ios;
#include<fstream>
using std::ifstream;
#include<string>
using std::string;

class ValueType{
	public:
		const static unsigned int Undefined = 0;
		const static unsigned int Double = 1;
		const static unsigned int String = 2;

};
class  Token{
	public:
	const static unsigned int Undefine = 0;
	const static unsigned int Identity = 1;
	const static unsigned int KeyFind  = 2;
	const static unsigned int KeyIn = 3;
	const static unsigned int KeyWhen  = 4;
	const static unsigned int LeftParentheses = 5;
	const static unsigned int RightParentheses = 6;
	const static unsigned int Comma = 7;
	

	unsigned int Type;
	unsigned int ValueType;
	void* Value;//it's hard

	Token(unsigned int type, unsigned int valueType){

		this->Type = type;
		this->ValueType = valueType;
		this->Value = 0;
	}

	Token(const Token& t){
		this->ValueType = t.ValueType;
		this->Type = t.Type;	

		if(this->ValueType == ValueType::Double){
			this->SetValue( t.GetDouble());	
		}
		else if(this->ValueType == ValueType::String){
			this->SetValue(t.GetString().c_str());
		}
	}

	~Token(){
		if(Value){
			if(this->ValueType == ValueType::Double){
				delete  (double *)Value;
			}
			else if(this->ValueType == ValueType::String){
				delete (string*) Value;
			}
		}
	}

	void SetValue(double value){
		if(this->ValueType == ValueType::Double){
			delete  (double *)Value;
		}
		else if(this->ValueType == ValueType::String){
			delete (string*) Value;
		}
		double* d =  new double() ;	
		*d = value;
		this->Value = (void*)d;
	}

	void SetValue(const char* value){
		if(this->ValueType == ValueType::Double){
			delete  (double *)Value;
		}
		else if(this->ValueType == ValueType::String){
			delete (string*) Value;
		}
		string* s = new string(value);
		this->Value = (void*)s;
		
	}
	
	double GetDouble() const{
		double result;
		result = *((double*)this->Value);
		return result;
	}

	string GetString() const{
		string result(*((string*)this->Value) );
		return result;
	}

	

};

class Lexical{
	private:
	int length;
	int begin;
	char*  context;// may using cache later  ,nerver use this outside 
	public:
	string FileName;
	
	public:
	Lexical(const char* fileName):FileName(fileName){

	}

	private:
	
	void loadContext(){
		this->begin = 0;

		ifstream f;
		f.open(FileName.c_str(),ios::binary);
		f.seekg(0,ios::end);

		this->length = f.tellg();
		f.seekg(0,ios::beg);

		context = new char[length];
		
		f.read(context,length);

		f.close();
		
	}
	
	
};
#endif
